﻿namespace Raven
{
    public class RailGun : RavenWeapon
    {
        public RailGun(RavenBot owner) 
            : base(WeaponType.type_rail_gun, Constants.RailGun_DefaultRounds, Constants.RailGun_MaxRoundsCarried, 
                Constants.RailGun_FiringFreq, Constants.RailGun_IdealRange, Constants.Slug_MaxSpeed, owner)
        {
            //setup the fuzzy module
            InitializeFuzzyModule();
        }

        protected override void InitializeFuzzyModule()
        {
            _fuzzyModule = new FuzzyModule();
            FuzzyVariable DistanceToTarget = _fuzzyModule.CreateFLV("DistanceToTarget");
  
            FzSet Target_Close = DistanceToTarget.AddLeftShoulderSet("Target_Close", 0, 25, 150);
            FzSet Target_Medium = DistanceToTarget.AddTriangularSet("Target_Medium", 25, 150, 300);
            FzSet Target_Far = DistanceToTarget.AddRightShoulderSet("Target_Far", 150, 300, 1000);

            FuzzyVariable Desirability = _fuzzyModule.CreateFLV("Desirability");
  
            FzSet VeryDesirable = Desirability.AddRightShoulderSet("VeryDesirable", 50, 75, 100);
            FzSet Desirable = Desirability.AddTriangularSet("Desirable", 25, 50, 75);
            FzSet Undesirable = Desirability.AddLeftShoulderSet("Undesirable", 0, 25, 50);

            FuzzyVariable AmmoStatus = _fuzzyModule.CreateFLV("AmmoStatus");
            FzSet Ammo_Loads = AmmoStatus.AddRightShoulderSet("Ammo_Loads", 15, 30, 100);
            FzSet Ammo_Okay = AmmoStatus.AddTriangularSet("Ammo_Okay", 0, 15, 30);
            FzSet Ammo_Low = AmmoStatus.AddTriangularSet("Ammo_Low", 0, 0, 15);

  

            _fuzzyModule.AddRule(new FzAND(Target_Close, Ammo_Loads), new FzFairly(Desirable));
            _fuzzyModule.AddRule(new FzAND(Target_Close, Ammo_Okay),  new FzFairly(Desirable));
            _fuzzyModule.AddRule(new FzAND(Target_Close, Ammo_Low), Undesirable);

            _fuzzyModule.AddRule(new FzAND(Target_Medium, Ammo_Loads), VeryDesirable);
            _fuzzyModule.AddRule(new FzAND(Target_Medium, Ammo_Okay), Desirable);
            _fuzzyModule.AddRule(new FzAND(Target_Medium, Ammo_Low), Desirable);

            _fuzzyModule.AddRule(new FzAND(Target_Far, Ammo_Loads), new FzVery(VeryDesirable));
            _fuzzyModule.AddRule(new FzAND(Target_Far, Ammo_Okay), new FzVery(VeryDesirable));
            _fuzzyModule.AddRule(new FzAND(Target_Far, new FzFairly(Ammo_Low)), VeryDesirable);
        }

        public override void Destroy()
        {
        }

        public override void ShootAt(Vector2 pos)
        {
            if (NumRoundsRemaining() > 0 && isReadyForNextShot() && _owner.hasLOSto(pos))
            {
                //fire a round
                _owner.GetWorld().AddRailGunSlug(_owner, pos);

                UpdateTimeWeaponIsNextAvailable();

                DecrementNumRounds();

                //add a trigger to the game so that the other bots can hear this shot
                //(provided they are within range)
                _owner.GetWorld().GetMap().AddSoundTrigger(_owner, Constants.RailGun_SoundRange);
            }
        }

        public override Fix GetDesirability(Fix DistToTarget)
        {
            if (_numRoundsLeft == 0)
            {
                _lastDesirabilityScore = 0;
            }
            else
            {
                //fuzzify distance and amount of ammo
                _fuzzyModule.Fuzzify("DistanceToTarget", DistToTarget);
                _fuzzyModule.Fuzzify("AmmoStatus", _numRoundsLeft);
                
                _lastDesirabilityScore = _fuzzyModule.DeFuzzify("Desirability");
            }

            return _lastDesirabilityScore;
        }
    }
}